#include "StdAfx.h"
#include "ForestLoaderDemoState.h"

#include "CoreEngine.h"
#include "MainState.h"

#include <sstream>

namespace
{
	template <typename T> std::string ToString(const T& t)
	{
		std::ostringstream os;
		os << t;
		return os.str();
	};
}

ForestLoaderDemoState::ForestLoaderDemoState()
	: FEApplication(), FEngine::KeyboardInputListener(), FEngine::MouseInputListener()
{
	mCameraHandler			= NULL;
	mStatPanel				= NULL;
	mForestLoader			= NULL;
	mForestObjectNode		= NULL;
	mEntityTexture			= NULL;
	mShowLoader				= true;
}

ForestLoaderDemoState::~ForestLoaderDemoState()
{
	FEngine::InputManager::getInstance()->unregisterKeyboardInputListener(this);
	FEngine::InputManager::getInstance()->unregisterMouseInputListener(this);
	
	delete mCameraHandler;
	delete mStatPanel;
	if (mForestLoader)
		delete mForestLoader;
	
	for (std::list<FEngine::Entity*>::iterator it = mListEntity.begin(); it != mListEntity.end(); ++it)
		delete *it;

	if (mForestObjectNode)
		delete mForestObjectNode;
	
	for (std::list<FEngine::TextLabel*>::iterator it = mListLabels.begin(); it != mListLabels.end(); ++it)
		delete *it;

	if (mLabelNumberObject)
		delete mLabelNumberObject;
	if (mLabelTypeObject)
		delete mLabelTypeObject;

	if (mEntityTexture)
		mEntityTexture->Release();
	if (mGround)
		delete mGround;
}

void ForestLoaderDemoState::initialize()
{
	FEngine::FEApplication::initialize();
	FEngine::InputManager::getInstance()->registerKeyboardInputListener(this);
	FEngine::InputManager::getInstance()->registerMouseInputListener(this);
	
	FEngine::CoreEngine::getInstance()->getCamera()->setFarDistanceView(750.0f);

	mCameraHandler = new FEngine::FreeCameraHandler(FEngine::CoreEngine::getInstance()->getCamera(), Vector3(0, 3, -50), Vector3(0, 0, 1));
	addChild(mCameraHandler);
	
	FEngine::CoreEngine::getInstance()->disableFog();
	
	FEngine::CoreEngine::getInstance()->setSkyDome("skydome1.dds", 1.0f);

	mStatPanel = new StatPanel();
	addGUIElement(mStatPanel);


	mListLabels.push_back(new FEngine::TextLabel("This show how the ForestLoader works", 350, 10, 0, 200, 22, FEngine::ColorRGB(255, 255, 255)));
	addGUIElement(mListLabels.back());
	mListLabels.push_back(new FEngine::TextLabel("The ForestLoader handle the creation and management of 3D objects", 350, 40, 0, 200, 22, FEngine::ColorRGB(255, 255, 255)));
	addGUIElement(mListLabels.back());
	mListLabels.push_back(new FEngine::TextLabel("Press SPACE to switch between the ForestLoader and standard 3D objects", 350, 70, 0, 200, 22, FEngine::ColorRGB(255, 255, 255)));
	addGUIElement(mListLabels.back());

	
	// Create the forest loader
	Vector2 area(100, 100);
	int blockSize = 30;
	mForestLoader = new FEngine::ForestLoader(blockSize, 2 + (int)area.x / blockSize, Vector2(-blockSize + -area.x / 2, -blockSize + -area.y / 2), 750, 750);
	mForestObjectNode = new FEngine::Node();
	mForestLoader->createObject("tree1.x", "tree1.png");
	Vector3 posPrim;
	for (int i = (int)-area.x / 2; i < area.x / 2; i += 3)
	{
		for (int j = (int)-area.y / 2; j < area.y / 2; j += 3)
		{
			posPrim = Vector3((float)(rand() % 5) - 2.5f, 0, (float)(rand() % 5) - 2.5f);
			posPrim += Vector3((float)i, 0, (float)j);
			float scale = (float)(rand() % 4) / 10.0f + 0.8f;
			scale /= 4;

			mForestLoader->addObject(posPrim, Vector3(0, 0, (float)(rand() % 360)), Vector3(scale, scale, scale));
		}
	}
	
	
	// Create the 3D objects
	
	// Load the texture one time
	if (D3DXCreateTextureFromFileEx(FEngine::CoreEngine::getInstance()->getDeviceInterface(), L"tree1.png", D3DX_DEFAULT, D3DX_DEFAULT, 
								D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, 
								NULL, NULL, &mEntityTexture) != D3D_OK)
		throw FEngine::FEngineException("ForestLoaderDemoState", "initialize", "Cannot load the texture file");


	area = Vector2(70, 70);
	FEngine::Entity* entity;
	for (int i = (int)-area.x / 2; i < area.x / 2; i += 3)
	{
		for (int j = (int)-area.y / 2; j < area.y / 2; j += 3)
		{
			posPrim = Vector3((float)(rand() % 5) - 2.5f, 0, (float)(rand()  % 5) - 2.5f);
			posPrim += Vector3((float)i, 0, (float)j);
			float scale = (float)(rand() % 4) / 10.0f + 0.8f;
			
			entity = new FEngine::Entity("tree1.x", mEntityTexture);
			mForestObjectNode->addChild(entity);
			entity->setPosition(posPrim);
			entity->setRotation(0, 0, (float)(rand() % 360));
			entity->setScale(scale / 4);

			mListEntity.push_back(entity);
		}
	}

	
	// Create the ground
	mGround = new FEngine::PrimitiveCube(1000.0f);
	addChild(mGround);
	mGround->translate(0, -1000.0f, 0);
	mGround->setColor(20, 50, 20);
	
	if (!mShowLoader)
		addChild(mForestObjectNode);
	
	mLabelTypeObject = new FEngine::TextLabel("ForestLoader", 20, 200, 100, 30, 22, FEngine::ColorRGB(255, 255, 255));
	addGUIElement(mLabelTypeObject);
	mLabelNumberObject = new FEngine::TextLabel("Number of object :", 10, 240, 100, 30, 22, FEngine::ColorRGB(255, 255, 255));
	addGUIElement(mLabelNumberObject);
}

void ForestLoaderDemoState::update(double _elapsedTime)
{
	FEApplication::update(_elapsedTime);

	if (mShowLoader)
		mForestLoader->update(_elapsedTime);
}

void ForestLoaderDemoState::updateGUI(double _elapsedTime)
{
	FEApplication::updateGUI(_elapsedTime);
	
	if (mShowLoader)
	{
		mLabelTypeObject->setText("ForestLoader");
		mLabelNumberObject->setText("Number of object (visible / total) : " + ToString(mForestLoader->getNumberVisibleObject()) + " / " + ToString(mForestLoader->getNumberVisibleImpostor()));
	}
	else
	{
		mLabelTypeObject->setText("3D objects");
		mLabelNumberObject->setText("Number of object : " + ToString(mListEntity.size()));
	}
}


void ForestLoaderDemoState::render(double _elapsedTime)
{
	FEApplication::render(_elapsedTime);

	if (mShowLoader)
		mForestLoader->render(_elapsedTime);
}

void ForestLoaderDemoState::keyPressed(int _key)
{
	if (_key == FEngine::InputManager::KEY_SPACE)
	{
		mShowLoader = !mShowLoader;

		if (mShowLoader)
			removeChild(mForestObjectNode);
		else
			addChild(mForestObjectNode);
	}

	if (_key == FEngine::InputManager::KEY_ESCAPE)
	{
		MainState* newApp = new MainState();
		FEngine::CoreEngine::getInstance()->setApplication(newApp);
	}
}

void ForestLoaderDemoState::keyReleased(int _key)
{
}

void ForestLoaderDemoState::mouseButtonPressed(int _button, const Vector2& _position)
{
}

void ForestLoaderDemoState::mouseButtonReleased(int _button, const Vector2& _position)
{
}

void ForestLoaderDemoState::mouseMoved(const Vector2& _delta)
{
}
